package com.culture.bootdemo.controller.bitmap;

import com.google.common.collect.Lists;
import io.swagger.models.auth.In;
import org.roaringbitmap.RoaringBitmap;
import org.roaringbitmap.longlong.Roaring64Bitmap;
import org.roaringbitmap.longlong.Roaring64NavigableMap;

import java.util.List;

/**
 * @Author: wenjl
 * @Date: 2021/6/7 16:37
 * @Description: RoaringBitmap
 *
 * Container原理:
 *      ArrayContainer: 当桶内数据的基数不大于4096时，会采用它来存储，其本质上是一个unsigned short类型的有序数组。
 *      BitmapContainer: 当桶内数据的基数大于4096时，会采用它来存储,用长度固定为1024的unsigned long型数组表示
 *      RunContainer:  它使用可变长度的unsigned short数组存储用行程长度编码（RLE）压缩后的数据。
 *
 */
public class RoaringBitmapDemo {
    //TODO 待研究

    public void test() {
        RoaringBitmap rr = RoaringBitmap.bitmapOf(1, 2, 3, 1000);
        RoaringBitmap rr2 = new RoaringBitmap();
        rr2.add(4000L, 4255L);
        // 返回存储在这个位图中的第j个值。
        // 提供的值需要比基数小，否则抛出IllegalArgumentException异常。
        // 最小的值在索引0处。注意，这个函数与rank函数的约定不同，后者在对最小值排序时返回1。
        // would return the third value or 1000
        rr.select(3);
        // Rank返回小于或等于x的整数的数目(Rank(∞)是GetCardinality())。
        // 如果将最小的值作为参数提供，则该函数将返回1。
        // 如果提供的值小于最小值，则返回0。
        // would return the rank of 2, which is index 1
        rr.rank(2);
        // will return true
        rr.contains(1000);
        // will return false
        rr.contains(7);
        // 并集
        // new bitmap
        RoaringBitmap rror = RoaringBitmap.or(rr, rr2);
        //
        //in-place computation
        rr.or(rr2);
        // true
        boolean equals = rror.equals(rr);
        if (!equals) {
            throw new RuntimeException("bug");
        }
        // number of values stored?
        long cardinality = rr.getLongCardinality();
        System.out.println(cardinality);
        long size = 0;
        // a "forEach" is faster than this loop, but a loop is possible:
        for (int i : rr) {
            System.out.println(i);
            size++;
        }
        // 259
        System.out.println(size);
    }

    public static void roaring64NavigableMapDemo() {
        Roaring64NavigableMap a1 = Roaring64NavigableMap.bitmapOf(1L, 2L, 3L, 4L, 5L);
        System.out.println(a1);

//        Roaring64NavigableMap b1 = new Roaring64NavigableMap();
//        b1.add(3L,20L);
        Roaring64NavigableMap b1 = Roaring64NavigableMap.bitmapOf(6L, 7L, 8L, 4L, 5L);
        System.out.println(b1);

        a1.or(b1);
        System.out.println(a1);
        System.out.println(b1);
    }

    public static void roaring64BitmapDemo() {
        Roaring64Bitmap a1 = Roaring64Bitmap.bitmapOf(1L, 2L, 3L, 4L, 5L);
        System.out.println(a1);

        Roaring64Bitmap b1 = new Roaring64Bitmap();
        b1.add(4L, 20L);
        System.out.println(b1);
//        a1.or(b1);
        a1.and(b1);
//        a1.andNot(b1);
        System.out.println(a1);
        System.out.println(b1);
    }

    public static void roaringBitmapDemo() {
        List<Integer> list = Lists.newArrayList(1, 2, 3, 4);
        RoaringBitmap demo = RoaringBitmap.bitmapOf(list.stream().mapToInt(Integer::intValue).toArray());

        RoaringBitmap a = RoaringBitmap.bitmapOf(1, 2, 3, 1000);
        System.out.println(a);
        System.out.println(a.select(3));
        RoaringBitmap b = new RoaringBitmap();

        for (int i = 0; i < 10; i++) {
            b.add(i * 3);
        }
        System.out.println(b);
        System.out.println(b.select(3));

        //交集
        RoaringBitmap and = RoaringBitmap.and(a, b);
        //并集去重
        RoaringBitmap or = RoaringBitmap.or(a, b);
        System.out.println(and);
        System.out.println(or);

        System.out.println(and.getCardinality());
        System.out.println(or.getCardinality());

        RoaringBitmap rr2 = new RoaringBitmap();
        rr2.add(4000L, 4255L);
        System.out.println("---" + rr2);

    }

    public static void roaringBitmapDemo2() {
        RoaringBitmap a = RoaringBitmap.bitmapOf(1, 2, 3, 4, 5, 6, 10, 20, 50);
        RoaringBitmap b = RoaringBitmap.bitmapOf(1, 5, 20, 13, 432, 32, 54, 45, 54);
        System.out.println(a);

        //交集
        RoaringBitmap and = RoaringBitmap.and(a, b);

        //并集去重
        RoaringBitmap or = RoaringBitmap.or(a, b);

        RoaringBitmap c = RoaringBitmap.andNot(a, b);
        System.out.println("交集：" + and);
        System.out.println("并集：" + or);
        System.out.println("差集 a-b：" + c);

    }

    public static void main(String[] args) {
        roaringBitmapDemo2();
    }

}
